package cn.px.auth.controller;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;

import com.alibaba.fastjson2.JSONObject;
import cn.px.common.core.constant.Constants;
import cn.px.common.core.constant.LoginTypeConstants;
import cn.px.common.core.utils.StringUtils;
import cn.px.common.core.utils.http.HttpClient;
import cn.px.common.core.utils.http.HttpResponse;
import cn.px.common.redis.service.RedisService;
import cn.px.system.api.domain.SysUser;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;
import cn.px.auth.form.LoginBody;
import cn.px.auth.service.SysLoginService;
import cn.px.common.core.domain.R;
import cn.px.common.core.utils.JwtUtils;
import cn.px.common.security.auth.AuthUtil;
import cn.px.common.security.service.TokenService;
import cn.px.common.security.utils.SecurityUtils;
import cn.px.system.api.model.LoginUser;

import java.util.concurrent.TimeUnit;

/**
 * token 控制
 *
 * @author 品讯科技
 */
@Slf4j
@Api(tags = "用户登录")
@RestController
public class TokenController {
    @Autowired
    private TokenService tokenService;

    @Autowired
    private SysLoginService sysLoginService;

    @Resource
    private RedisService redisService;

    @Value("${wx.openIdUrl:https://api.weixin.qq.com/sns/jscode2session}")
    private String openIdUrl;

    @Value("${wx.appId:wxa6f12840b0fbee85}")
    private String appId;

    @Value("${wx.appSecret:0f6842127fde1133ef279e7cba348759}")
    private String secret;

    @Value("${wx.grantType:authorization_code}")
    private String grantType;

    @Value("${verificationCode.expireTime:}")
    private Long expireTime;

    @Value("${wx.access-token-url:https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=wxa6f12840b0fbee85&secret=0f6842127fde1133ef279e7cba348759}")
    private String accessTokenUrl;

    @Value("${wx.get-phone-url:https://api.weixin.qq.com/wxa/business/getuserphonenumber?access_token=%s}")
    private String getPhoneUrl;


    @ApiOperation(value = "用户登录")
    @PostMapping("login2")
    public R<?> login(@RequestBody LoginBody form) {
        LoginUser userInfo = new LoginUser();
        if (LoginTypeConstants.WECHAT_MIN_PROGRAM.equals(form.getThirdPartyFlag())) {
            if (StringUtils.isBlank(form.getPhonenumber()) || StringUtils.isBlank(form.getCode())) {
                return R.fail("手机号码/短信验证码不能为空");
            }
            String code = redisService.getCacheObject(form.getPhonenumber() + "-" + form.getCode());
            if (StringUtils.isBlank(code)) {
                return R.fail("短信验证码已失效");
            } else {
                if (!form.getCode().equals(code)) {
                    return R.fail("短信验证码错误");
                } else {
                    SysUser sysUser = sysLoginService.getSysUser(form.getPhonenumber());
                    if (sysUser == null) {
                        //注册用户信息
                        String password = "Zhbc@" + form.getPhonenumber().substring(form.getPhonenumber().length() - 6);
                        sysLoginService.register(form.getPhonenumber(), password);
                    }
                    userInfo = sysLoginService.loginByCode(form.getPhonenumber());
                }
            }
        } else if (LoginTypeConstants.ONE_CLICK_LOGIN.equals(form.getThirdPartyFlag())) {
            if (StringUtils.isBlank(form.getPhonenumber()) || StringUtils.isBlank(form.getCode())) {
                return R.fail("手机号码/openid不能为空");
            }
            String openid = redisService.getCacheObject(form.getPhonenumber());
            if (!form.getCode().equals(openid)) {
                return R.fail("openid错误");
            } else {
                SysUser sysUser = sysLoginService.getSysUser(form.getPhonenumber());
                if (sysUser == null) {
                    //注册用户信息
                    String password = "Zhbc@" + form.getPhonenumber().substring(form.getPhonenumber().length() - 6);
                    sysLoginService.register(form.getPhonenumber(), password);
                }
                userInfo = sysLoginService.loginByCode(form.getPhonenumber());
            }
        } else if (LoginTypeConstants.CAPTCHA_LOGIN.equals(form.getThirdPartyFlag())) {
            if (StringUtils.isBlank(form.getUsername())) {
                form.setUsername(form.getPhonenumber());
            }
            if ((StringUtils.isBlank(form.getPhonenumber()) && StringUtils.isBlank(form.getUsername()))
                    || StringUtils.isBlank(form.getCode()) || StringUtils.isBlank(form.getPassword())
                    || StringUtils.isBlank(form.getUuid())) {
                return R.fail("用户名、手机号码/用户密码/验证码/uuid不能为空");
            }
            String code = redisService.getCacheObject(Constants.CAPTCHA_CODE_KEY + form.getUuid());
            if (StringUtils.isBlank(code)) {
                return R.fail("验证码已失效");
            } else {
                if (!form.getCode().equals(code)) {
                    return R.fail("验证码错误");
                } else {
                    userInfo = sysLoginService.login(form.getUsername(), form.getPassword());
                }
            }
        } else {
            if (StringUtils.isBlank(form.getUsername())) {
                form.setUsername(form.getPhonenumber());
            }
            userInfo = sysLoginService.login(form.getUsername(), form.getPassword());
        }
        // 获取登录token
        return R.ok(tokenService.createToken(userInfo));
    }

    @ApiOperation(value = "退出登录")
    @DeleteMapping("logout")
    public R<?> logout(HttpServletRequest request) {
        String token = SecurityUtils.getToken(request);
        if (StringUtils.isNotEmpty(token)) {
            String username = JwtUtils.getUserName(token);
            // 删除用户缓存记录
            AuthUtil.logoutByToken(token);
            // 记录用户退出日志
            sysLoginService.logout(username);
        }
        return R.ok();
    }

    @ApiOperation(value = "刷新token")
    @PostMapping("refresh")
    public R<?> refresh(HttpServletRequest request) {
        LoginUser loginUser = tokenService.getLoginUser(request);
        if (StringUtils.isNotNull(loginUser)) {
            // 刷新令牌有效期
            tokenService.refreshToken(loginUser);
            return R.ok();
        }
        return R.ok();
    }

//    @ApiOperation(value = "用户注册")
//    @PostMapping("register")
//    public R<?> register(@RequestBody RegisterBody registerBody) {
//        // 用户注册
//        sysLoginService.register(registerBody.getUsername(), registerBody.getPassword());
//        return R.ok();
//    }

    @ApiOperation(value = "获取微信openId")
    @GetMapping("getWXOpenId")
    public R<?> register(String jsCode, String phoneNumber) {
        String openId = "";
        if (StringUtils.isBlank(jsCode)) {
            return R.fail("参数不能为空");
        }
        HttpResponse response = HttpClient.get()
                .url(openIdUrl)
                .header("Content-Type", "application/json")
                .body("appid", appId)
                .body("secret", secret)
                .body("js_code", jsCode)
                .body("grant_type", grantType)
                .newInvoker().execute();
        String result = response.to(String.class);
        System.out.println(result);
        if (StringUtils.isNotBlank(result)) {
            JSONObject jsonObject = JSONObject.parseObject(result);
            openId = jsonObject.getString("openid");
            redisService.setCacheObject(phoneNumber, openId, expireTime, TimeUnit.SECONDS);
        }
        return R.ok(openId, "获取微信openId成功");
    }

    @ApiOperation(value = "获取微信openId2")
    @GetMapping("getWXOpenId2")
    public R<?> register(String jsCode) {
        String openId = "";
        if (StringUtils.isBlank(jsCode)) {
            return R.fail("参数不能为空");
        }
        HttpResponse response = HttpClient.get()
                .url(openIdUrl)
                .header("Content-Type", "application/json")
                .body("appid", appId)
                .body("secret", secret)
                .body("js_code", jsCode)
                .body("grant_type", grantType)
                .newInvoker().execute();
        String result = response.to(String.class);
        System.out.println(result);
        if (StringUtils.isNotBlank(result)) {
            JSONObject jsonObject = JSONObject.parseObject(result);
            openId = jsonObject.getString("openid");
        }
        return R.ok(openId, "获取微信openId成功");
    }

    @ApiOperation(value = "获取微信手机号")
    @GetMapping("getWXPhone")
    public R<?> getWXPhone(String code) {
        String phone = "";
        if (StringUtils.isBlank(code)) {
            return R.fail("code不能为空");
        }
        String token = getWXToken();
        if (StringUtils.isBlank(token)) {
            return R.fail("token不能为空");
        }
        HttpResponse response = HttpClient.get()
                .url(String.format(getPhoneUrl, token))
                .isHttps()
                .header("Content-Type", "application/json")
                .body("code", code)
                .newInvoker().execute();
        String result = response.to(String.class);
        log.info("获取微信手机号接口返回结果："+ result);
        if (StringUtils.isNotBlank(result)) {
            JSONObject jsonObject = JSONObject.parseObject(result);
            if (StringUtils.isNotBlank(jsonObject.getString("phone_info"))) {
                JSONObject object = JSONObject.parseObject(jsonObject.getString("phone_info"));
                phone = object.getString("phoneNumber");
                return R.ok(phone, "获取微信手机号成功");
            }
        }
        return R.fail("获取微信手机号失败");
    }

    private String getWXToken() {
        String token = "";
        HttpResponse response = HttpClient.get()
                .url(accessTokenUrl)
                .isHttps()
                .header("Content-Type", "application/json")
                .newInvoker().execute();
        String result = response.to(String.class);
        log.info("获取微信token接口返回结果："+ result);
        if (StringUtils.isNotBlank(result)) {
            JSONObject jsonObject = JSONObject.parseObject(result);
            token = jsonObject.getString("access_token");
//            Long expireTime = jsonObject.getLong("expires_in");
//            redisService.setCacheObject("wx_access_token", token, expireTime, TimeUnit.SECONDS);
        }
        return token;
    }
}
